package org.xlp.db.bridge.defination;

import org.xlp.db.bridge.helper.DaoBridgeHelper;
import org.xlp.db.tableoption.annotation.XLPEntity;
import org.xlp.db.tableoption.handlers.result.DataSet;
import org.xlp.db.xml.XmlSQL;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Description: 查询执行工具类
 * <br/>date: 2024/4/26 15:45
 *
 * @version 1.0
 * @author: xlp
 */
class QueryExecuteUtils {
    /**
     * 执行查询SQL
     * @param xmlSQL 执行查询SQL对象
     * @param genericReturnType 返回值类型
     * @return 返回返回值对应的类型
     */
    public static Object executeQuery(XmlSQL xmlSQL, Type genericReturnType) {
        Class<?>[] classes = getRealClassAndGenericClass(genericReturnType);
        Class<?> returnType = classes[0];

        if (returnType == null) return null;

        if (returnType.getAnnotation(XLPEntity.class) != null){
            return DaoBridgeHelper.getBaseDao().find(xmlSQL);
        }

        if (returnType == Object[].class){
            return DaoBridgeHelper.getBaseDao().array(xmlSQL);
        }
        if (returnType == DataSet.class){
            return DaoBridgeHelper.getBaseDao().findDataSet(xmlSQL);
        }
        if (returnType == String.class){
            return String.valueOf(DaoBridgeHelper.getBaseDao().array(xmlSQL)[0]);
        }

        if (returnType == Integer.TYPE ||  returnType == Integer.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL).intValue();
        }

        if (returnType == Double.TYPE ||  returnType == Double.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL);
        }

        if (returnType == Short.TYPE ||  returnType == Short.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL).shortValue();
        }

        if (returnType == Byte.TYPE ||  returnType == Byte.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL).byteValue();
        }

        if (returnType == Long.TYPE ||  returnType == Long.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL).longValue();
        }

        if (returnType == Float.TYPE ||  returnType == Float.class){
            return DaoBridgeHelper.getBaseDao().max(xmlSQL).floatValue();
        }

        if (returnType == List.class){
            Class<?> cs = classes[1];
            if (cs != null){
                if (cs.getAnnotation(XLPEntity.class) != null){
                    return DaoBridgeHelper.getBaseDao().list(xmlSQL);
                }
                if (cs == Object[].class){
                    return DaoBridgeHelper.getBaseDao().listArray(xmlSQL);
                }

                if (cs == Map.class){
                    return DaoBridgeHelper.getBaseDao().listMap(xmlSQL);
                }
            }
            throw new NotAdaptReturnTypeException("未匹配到：[" + genericReturnType + "]返回类型");
        }

        if (returnType == Map.class){
            return DaoBridgeHelper.getBaseDao().map(xmlSQL);
        }

        if (Set.class == returnType){
            Class<?> cs = classes[1];
            if (cs != null){
                if (cs.getAnnotation(XLPEntity.class) != null){
                    return DaoBridgeHelper.getBaseDao().set(xmlSQL);
                }
                if (cs == Object[].class){
                    return new HashSet<>(DaoBridgeHelper.getBaseDao().listArray(xmlSQL));
                }

                if (cs == Map.class){
                    return new HashSet<>(DaoBridgeHelper.getBaseDao().listMap(xmlSQL));
                }
            }
            throw new NotAdaptReturnTypeException("未匹配到：[" + genericReturnType + "]返回类型");
        }

        if(returnType == Boolean.TYPE || returnType == Boolean.class){
            return !DaoBridgeHelper.getBaseDao().list(xmlSQL).isEmpty();
        }

        return DaoBridgeHelper.getBaseDao().array(xmlSQL)[0];
    }

    /**
     * 根据泛型类型获取实际类型和泛型对应的Class
     * @param returnType
     * @return [0]：实际类型， [1]: 泛型对应的Class
     */
    private static Class<?>[] getRealClassAndGenericClass(Type returnType){
        Class<?>[] classes = new Class[2];
        if (returnType instanceof Class){
           classes[0] = ((Class<?>) returnType);
        } else if (returnType instanceof ParameterizedType){
            ParameterizedType type = (ParameterizedType) returnType;
            Type actualTypeArgument = type.getActualTypeArguments()[0];
            classes[0] = (Class<?>) type.getRawType();
            if (actualTypeArgument instanceof Class){
                classes[1] = ((Class<?>) actualTypeArgument);
            } else if (actualTypeArgument instanceof ParameterizedType){
                classes[1] = ((Class<?>) ((ParameterizedType) actualTypeArgument).getRawType());
            }
        }
        return classes;
    }
}
